using Digitalmes.Application;
using Digitalmes.Common;
using Digitalmes.Common.Cache;
using Digitalmes.Common.Jwt;
using Polly;

namespace Digitalmes.ApiService.Hubs;

/// <summary>
/// 用户在线 Hub
/// </summary>
[NoApiSecurity]
[EnableCors("MyCors")]
public sealed class OnlineHub : Hub
{
    private readonly IHttpContextAccessor _accessor;

    public OnlineHub(IHttpContextAccessor accessor)
    {
        _accessor = accessor;
    }

    /// <summary>
    /// 发送消息
    /// </summary>
    /// <param name="userId"></param>
    [HubMethodName("SendKickOut")]
    public async Task SendKickOut(long userId)
    {
        var users = RedisService.Instance.Get<List<ClientUser>>(AppConsts.ONLINEUSERS);
        if (users != null)
        {
            var now = users.FirstOrDefault(m => m.Id == userId);
            if (now != null)
            {
                Context.Items.Remove(now.ConnectionId);
                users.Remove(now);
            }
            RedisService.Instance.SetJson(AppConsts.ONLINEUSERS, users);
        }
        await Clients.All.SendAsync("ReceiveMessage", "out", userId);
    }

    public override async Task OnConnectedAsync()
    {
        if (_accessor.HttpContext != null)
        {
            var token = _accessor.HttpContext.Request.Query["access_token"];
            var jwtToken = JwtAuthHandler.SerializeJwt(token!);

            var users = RedisService.Instance.Get<List<ClientUser>>(AppConsts.ONLINEUSERS);
            if (users == null)
            {
                users = new List<ClientUser>
                {
                    new ClientUser()
                    {
                        Id = jwtToken.Id,
                        ConnectionId = Context.ConnectionId,
                        Name = jwtToken.FullName
                    }
                };
                RedisService.Instance.SetJson(AppConsts.ONLINEUSERS, users);
            }
            else
            {
                var now = users.FirstOrDefault(m => m.Id == jwtToken.Id);
                if (now != null)
                {
                    Context.Items.Remove(now.ConnectionId);
                    users.Remove(now);
                }
                users.Add(new ClientUser()
                {
                    Id = jwtToken.Id,
                    ConnectionId = Context.ConnectionId,
                    Name = jwtToken.FullName
                });
                RedisService.Instance.SetJson(AppConsts.ONLINEUSERS, users);
            }
        }
        await base.OnConnectedAsync();
    }

    /// <summary>
    /// 断开
    /// </summary>
    /// <param name="exception"></param>
    /// <returns></returns>
    public override Task OnDisconnectedAsync(Exception? exception)
    {
        var users = RedisService.Instance.Get<List<ClientUser>>(AppConsts.ONLINEUSERS);
        if (users == null)
        {
            return base.OnDisconnectedAsync(exception);
        }

        string connid = Context.ConnectionId;
        var now = users.FirstOrDefault(m => m.ConnectionId == connid);
        if (now != null)
        {
            users.Remove(now);
        }

        RedisService.Instance.SetJson(AppConsts.ONLINEUSERS, users);
        return base.OnDisconnectedAsync(exception);
    }
}

/// <summary>
/// 用户信息
/// </summary>
public class ClientUser
{
    /// <summary>
    /// 唯一id
    /// </summary>
    public long Id { get; set; }

    /// <summary>
    /// 连接编号
    /// </summary>
    public string ConnectionId { get; set; }

    /// <summary>
    /// 应用编号
    /// </summary>
    public string AppId { get; set; }
    
    /// <summary>
    /// 登录人
    /// </summary>
    public string Name { get; set; }

    /// <summary>
    /// 操作类型
    /// </summary>
    public string Type { get; set; }
    
    /// <summary>
    /// 时间
    /// </summary>
    public DateTime Time { get; set; } = DateTime.Now;
}
